#pragma once
namespace graph_basic
{
   namespace details
   {
   
   }
   inline view_vertex_iterator_t::view_vertex_iterator_t(graph_view_t& view, vertex_iterator_pair_t its)
      :  view_(&view)
      ,  it_pair_(its)
   {
      if (it_pair_.first != it_pair_.second && !view_->vertex_predicate(*it_pair_.first))
         ++(*this);
   }
   inline void view_vertex_iterator_t::operator ++ ()
   {
      ++it_pair_.first;
      while( it_pair_.first != it_pair_.second && !view_->vertex_predicate(*it_pair_.first))
      {
         ++it_pair_.first;
      }
   }
   inline vertex_t const & view_vertex_iterator_t::operator * () const
   {
      return *it_pair_.first;
   }
   inline vertex_t& view_vertex_iterator_t::operator * ()
   {
      return *it_pair_.first;
   }
   inline bool view_vertex_iterator_t::operator != (view_vertex_iterator_t const & right)
   {
      return it_pair_.first != right.it_pair_.first;
   }
   
   inline view_edge_iterator_t::view_edge_iterator_t(graph_view_t& view, edge_iterator_pair_t its)
      :  view_(&view)
      ,  it_pair_(its)
   {
      if (it_pair_.first != it_pair_.second && !view_->edge_predicate(*it_pair_.first))
         ++(*this);
   }
   inline void view_edge_iterator_t::operator ++ ()
   {
      if(it_pair_.first != it_pair_.second) 
      {
         ++it_pair_.first;
         while( it_pair_.first != it_pair_.second && !view_->edge_predicate(*it_pair_.first) )
         {
            ++it_pair_.first;
         }
      }
   }
   inline edge_t const view_edge_iterator_t::operator * () const
   {
      return *it_pair_.first;
   }
   inline edge_t view_edge_iterator_t::operator * ()
   {
      return *it_pair_.first;
   }
   inline bool view_edge_iterator_t::operator != (view_edge_iterator_t const & right) const
   {
      return it_pair_.first != it_pair_.second;
   }
   
   inline view_adj_edges_iterator_t::view_adj_edges_iterator_t(vertex_id_t source_id, graph_view_t& view,
                                                               adj_edges_iterator_pair_t its)
      :  it_pair_(its)
      ,  view_(&view)
   {
      if (it_pair_.first != it_pair_.second && !view.edge_predicate(*it_pair_.first))
         ++(*this);
   }
   inline void view_adj_edges_iterator_t::operator ++ ()
   {
      ++it_pair_.first;
      while( it_pair_.first != it_pair_.second && !view_->edge_predicate(*it_pair_.first) )
      {
         ++it_pair_.first;
      }
   }
   inline edge_t const view_adj_edges_iterator_t::operator * () const
   {
      return *it_pair_.first;
   }
   inline edge_t view_adj_edges_iterator_t::operator * ()
   {
      return *it_pair_.first;
   }
   inline bool view_adj_edges_iterator_t::operator != (view_adj_edges_iterator_t const & right) const
   {
      return it_pair_.first != right.it_pair_.first;
   }
   
   inline view_adj_vertices_iterator_t::view_adj_vertices_iterator_t(vertex_id_t source_v_id, 
                                                                     graph_view_t& view, 
                                                                     adj_edges_iterator_pair_t its)
      :  it_pair_(adj_edges(source_v_id, view.get_graph()))
      ,  view_(&view)
   {
      if (it_pair_.first != it_pair_.second && !view.edge_predicate(*it_pair_.first))
         ++(*this);
   }
   inline void view_adj_vertices_iterator_t::operator ++ ()
   {
      ++it_pair_.first;
      while( it_pair_.first != it_pair_.second && !view_->edge_predicate(*it_pair_.first) )
      {
         ++it_pair_.first;
      }
   }
   inline vertex_t const & view_adj_vertices_iterator_t::operator * () const
   {
      return view_->get_graph()[(*it_pair_.first).get_target_vertex_id().vertex_in_graph_id_];
   }
   inline vertex_t& view_adj_vertices_iterator_t::operator * ()
   {
      return view_->get_graph()[(*it_pair_.first).get_target_vertex_id().vertex_in_graph_id_];
   }
   inline bool view_adj_vertices_iterator_t::operator != (view_adj_vertices_iterator_t const & right)
   {
      return it_pair_.first != right.it_pair_.first;
   }
   inline view_vertex_iterator_pair_t vertices(graph_view_t& view)
   {
      vertex_iterator_pair_t its = vertices(view.get_graph());
      return view_vertex_iterator_pair_t(view_vertex_iterator_t(view, its), view_vertex_iterator_t(its.second));
   }
   inline view_edge_iterator_pair_t edges(graph_view_t& view)
   {
      edge_iterator_pair_t its = edges(view.get_graph());
      return view_edge_iterator_pair_t(view_edge_iterator_t(view, its), view_edge_iterator_t(its.second));
   }
   inline view_adj_edges_iterator_pair_t adj_edges(vertex_id_t source_v_id, graph_view_t& view)
   {
      adj_edges_iterator_pair_t its = adj_edges(source_v_id, view.get_graph());
      return view_adj_edges_iterator_pair_t(view_adj_edges_iterator_t(source_v_id, view, its), view_adj_edges_iterator_t(its.second));
   }
   inline view_adj_vertices_iterator_pair_t adj_vertices(vertex_id_t source_v_id, graph_view_t& view)
   {
      adj_edges_iterator_pair_t its = adj_edges(source_v_id, view.get_graph());
      return view_adj_vertices_iterator_pair_t(view_adj_vertices_iterator_t(source_v_id, view, its), view_adj_vertices_iterator_t(its.second));
   }
}